package top.lidee.common.service.twice.management.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.transaction.annotation.Transactional;
import top.lidee.common.dto.AccountInfo;
import top.lidee.common.enums.StatusEnum;
import top.lidee.common.service.CateService;
import top.lidee.common.service.twice.management.BmsManagerService;
import top.lidee.common.util.CommonUtil;
import top.lidee.framework.enums.CommonExceptionEnum;
import top.lidee.framework.result.GlobalCheck;
import top.lidee.framework.result.PageUtils;
import top.lidee.framework.result.ResponseResult;
import top.lidee.module.backendApi.twice.page.Query;
import top.lidee.repository.mapper.twice.management.BmsManagerMapper;
import top.lidee.repository.model.twice.pojo.management.BmsManagerEntity;
import top.lidee.repository.model.twice.vo.management.ManagerAddVo;
import top.lidee.repository.model.twice.vo.management.ManagerVo;
import top.lidee.utils.CopyBean;
import top.lidee.utils.IpUtil;
import top.lidee.utils.MyCollUtil;

import java.util.*;
import java.util.stream.Collectors;

import static top.lidee.framework.constant.ManagerStatus.*;


@Service("bmsManagerService")
public class BmsManagerServiceImpl extends ServiceImpl<BmsManagerMapper, BmsManagerEntity> implements BmsManagerService {


    /**
     * @param params
     * @return top.lidee.framework.result.PageUtils
     * @description 条件查询
     * @author zhangyiheng
     * @date 2024/9/23 23:56
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, AccountInfo accountInfo, String ipAddr) {
        //人员名称/手机号
        String key = (String) params.get("key");
        //状态
        String status = (String) params.get("status");
        //省
        String province = (String) params.get("province");
        //市
        String city = (String) params.get("city");
        //区/县
        String county = (String) params.get("county");

        LambdaQueryWrapper<BmsManagerEntity> wrapper = Wrappers.<BmsManagerEntity>lambdaQuery()
                .and(StrUtil.isNotBlank(key), wq -> wq.like(StrUtil.isNotBlank(key), BmsManagerEntity::getName, key)
                        .or().eq(StrUtil.isNotBlank(key), BmsManagerEntity::getPhone, key))
                .eq(StrUtil.isNotBlank(province), BmsManagerEntity::getProvince, province)
                .eq(StrUtil.isNotBlank(city), BmsManagerEntity::getCity, city)
                .eq(StrUtil.isNotBlank(county), BmsManagerEntity::getCounty, county);

        if (StrUtil.isNotBlank(status)) {

            if (Objects.equals(status, StatusEnum.ENABLED.getKey())) {
                wrapper.and(wq -> wq.eq(BmsManagerEntity::getStatus, StatusEnum.ENABLED.getKey()));
            } else if (Objects.equals(status, StatusEnum.FORBIDDEN.getKey())) {
                wrapper.and(wq -> wq.eq(BmsManagerEntity::getStatus, StatusEnum.FORBIDDEN.getKey()));
            }
        }
        Integer managerId = GlobalCheck.checkManagerAdmin(accountInfo.getManagerId());
        //admin查询所有
        if (!Objects.equals(managerId, ADMIN)) {
            wrapper.eq(BmsManagerEntity::getHigherId, managerId);
        }

        IPage<BmsManagerEntity> page = this.page(
                new Query<BmsManagerEntity>().getPage(params),
                wrapper
        );
        List<BmsManagerEntity> records = page.getRecords();

        //查询创建人名称和上级名称
        List<ManagerVo> vos = new ArrayList<>();
        if (MyCollUtil.isNotEmpty(records)) {
            vos = records.stream().map(po -> {
                ManagerVo managerVo = CopyBean.copyBean(po, ManagerVo.class);
                managerVo.setRealName(po.getName());
                if (!Objects.equals(po.getCreateManagerId(), TOP1)) {
                    managerVo.setCreateManagerName(Optional.ofNullable(this.getById(po.getCreateManagerId()).getName()).orElse(""));
                }
                if (!Objects.equals(po.getHigherId(), TOP1)) {
                    managerVo.setHigherName(Optional.ofNullable(this.getById(po.getHigherId()).getName()).orElse(""));
                }
                managerVo.setLastTime(DateUtil.date().toLocalDateTime());
                managerVo.setLoggedIp(ipAddr);
                return managerVo;
            }).collect(Collectors.toList());

            //树化并排序
            vos = getCategoryTreeVos(vos);

            IPage<ManagerVo> pageVo = new Page<>();
            pageVo.setTotal(page.getTotal());
            pageVo.setRecords(vos);
            pageVo.setPages(page.getPages());
            pageVo.setSize(page.getSize());
            pageVo.setCurrent(page.getCurrent());

            return new PageUtils(pageVo);
        }

        return new PageUtils(page);
    }

    private List<ManagerVo> getCategoryTreeVos(List<ManagerVo> list) {
        List<ManagerVo> vos = CopyBean.copyBeanList(list, ManagerVo.class);

        Map<Integer, ManagerVo> map = new HashMap<>();

        for (ManagerVo vo : vos) {
            map.put(vo.getManagerId(), vo);
        }

        List<ManagerVo> vos1 = new ArrayList<>();

        for (ManagerVo value : map.values()) {
            ManagerVo fatherCategory = map.get(value.getHigherId());

            if (!Objects.isNull(fatherCategory)) {
                //说明有父分类
                if (CollUtil.isEmpty(fatherCategory.getChildren())) {
                    fatherCategory.setChildren(new ArrayList<>());
                }
                fatherCategory.getChildren().add(value);
                //排序
                categorySonSort(fatherCategory.getChildren());
            } else {
                vos1.add(value);
                categorySonSort(vos1);
            }
        }
        return vos1;
    }


    private void categorySonSort(List<ManagerVo> sonSort) {

        sonSort.sort(new Comparator<ManagerVo>() {
            @Override
            public int compare(ManagerVo o1, ManagerVo o2) {
                return (o1.getManagerId() == null ? 0 : o1.getManagerId()) - (o2.getManagerId() == null ? 0 : o2.getManagerId());
            }
        });
    }



    /**
     * @param params
     * @return java.util.List<top.lidee.repository.model.twice.pojo.management.BmsManagerEntity>
     * @description 根据条件查询人员
     * @author zhangyiheng
     * @date 2024/9/23 16:14
     */
    @Override
    public List<BmsManagerEntity> queryManagerByParams(Map<String, Object> params) {
        String status = (String) params.get("status");
        Integer managerId = (Integer) params.get("managerId");


        List<BmsManagerEntity> list = this.list(Wrappers.<BmsManagerEntity>lambdaQuery()
                .eq(!Objects.isNull(managerId), BmsManagerEntity::getManagerId, managerId)
                .eq(StrUtil.isNotBlank(status), BmsManagerEntity::getStatus, status));


        return list;
    }

    /**
     * @param managerAddVo
     * @return void
     * @description 后台管理系统-人员表新增下级
     * @author zhangyiheng
     * @date 2024/9/23 23:24
     */
    @Override
    @Transactional
    public ResponseResult saveManager(ManagerAddVo managerAddVo, AccountInfo accountInfo) {
        Integer managerId = accountInfo.getManagerId();

        if (Objects.isNull(managerId) || Objects.equals(managerId, 0)) {
            return ResponseResult.errorResult(CommonExceptionEnum.NOT_PERMISSION);
        }

        //当前人员
        BmsManagerEntity manager = this.getById(managerId);

        BmsManagerEntity managerEntity = CopyBean.copyBean(managerAddVo, BmsManagerEntity.class);


        //判断市級只能发展4个市级代理、区县级代理不受限制。
        //区县级代理不受限制。
        long count;
        switch (manager.getLevel()) {
            case LEVE_ADMIN: //admin
                if (!StrUtil.equalsAny(managerAddVo.getLevel(), MUNICIPAL, DISTRICT)) {
                    return ResponseResult.errorResult(CommonExceptionEnum.DLDJCW);
                }

                if (managerAddVo.getLevel().equals(MUNICIPAL)) {//市 4个
                    count = getCount(managerAddVo, manager, MUNICIPAL);
                    if (Objects.equals(count, 4)) {
                        return ResponseResult.errorResult(CommonExceptionEnum.FZSJDLSLDDSX.getCode(), StrUtil.format(CommonExceptionEnum.FZSJDLSLDDSX_.getMsg(), managerAddVo.getProvince()));
                    }
                }
                managerEntity.setLevel(managerAddVo.getLevel());
                break;
            case MUNICIPAL: //市级
                if (Objects.nonNull(managerAddVo.getLevel())&&!Objects.equals(managerAddVo.getLevel(), DISTRICT)) {
                    return ResponseResult.errorResult(CommonExceptionEnum.DLDJCW);
                }
                managerEntity.setLevel(DISTRICT);
                break;
            case DISTRICT:
                return ResponseResult.errorResult(CommonExceptionEnum.QXJBNXZXJDLS);
            default:
                return ResponseResult.errorResult(CommonExceptionEnum.DLDJFPCW_QCS);
        }

        //判断新增下级的账号/手机号是否重复
        if (phoneExist(managerAddVo.getPhone())) {
            return ResponseResult.errorResult(CommonExceptionEnum.SJHYCZ);
        }
        if (emailExist(managerAddVo.getEmail())) {
            return ResponseResult.errorResult(CommonExceptionEnum.YXYCZ);
        }

        managerEntity.setName(managerAddVo.getRealName());
        managerEntity.setInvitationCode(CommonUtil.getInvitationCode());
        managerEntity.setCreateManagerId(managerId);
        managerEntity.setUpdateManagerId(managerId);
        managerEntity.setHigherId(managerId);

        //保存下级
        this.save(managerEntity);

        //修改下级人数
        this.update(Wrappers.<BmsManagerEntity>lambdaUpdate()
                .set(BmsManagerEntity::getTotalLower, Optional.ofNullable(manager.getTotalLower()).orElse(0) + 1)
                .eq(BmsManagerEntity::getManagerId, managerId));

        return ResponseResult.ok();
    }


    private long getCount(ManagerAddVo managerAddVo, BmsManagerEntity manager, String leve) {
        long count;
        count = this.count(Wrappers.<BmsManagerEntity>lambdaQuery()
                .eq(BmsManagerEntity::getLevel, leve)
                .eq(BmsManagerEntity::getCity, managerAddVo.getCity())
                .eq(BmsManagerEntity::getHigherId, manager.getManagerId()));
        return count;
    }

    //校验邮箱是否重复
    private boolean emailExist(String email) {
        if (StrUtil.isNotBlank(email)) {
            long count = this.count(Wrappers.<BmsManagerEntity>lambdaQuery()
                    .eq(BmsManagerEntity::getEmail, email));
            return count > 0L;
        }
        return false;
    }

    //校验手机号是否重复
    private boolean phoneExist(String phone) {
        long count = this.count(Wrappers.<BmsManagerEntity>lambdaQuery()
                .eq(BmsManagerEntity::getPhone, phone));
        return count > 0L;
    }

    /**
     * @param managerId
     * @return void
     * @description 后台管理系统-修改状态
     * @author zhangyiheng
     * @date 2024/9/24 00:40
     */
    @Override
    @Transactional
    public ResponseResult updateStatus(Integer managerId, AccountInfo accountInfo) {

        Integer id = GlobalCheck.checkManagerAdmin(accountInfo.getManagerId());

        //确定上下级关系
        BmsManagerEntity managerEntity = determineTheSubordinateRelationship(managerId, id);

        //查询下级是否存在下级
        ResponseResult responseResult = hasNext(managerId, managerEntity);
        if (!Objects.isNull(responseResult)) {
            return responseResult;
        }

        //修改状态
        String status = "";
        if (Objects.equals(managerEntity.getStatus(), StatusEnum.ENABLED.getKey())) {
            status = StatusEnum.ENABLED.getKey();
        } else {
            status = StatusEnum.FORBIDDEN.getKey();
        }

        this.update(Wrappers.<BmsManagerEntity>lambdaUpdate()
                .set(BmsManagerEntity::getStatus, status)
                .eq(BmsManagerEntity::getManagerId, managerId));

        return ResponseResult.ok();

    }

    /**
     * @param managerId
     * @return com.yufubao.model.pojo.management.authorization.ManagerEntity
     * @description 确定上下级关系
     * @author zhangyiheng
     * @date 2024/9/12 13:52
     */
    private BmsManagerEntity determineTheSubordinateRelationship(Integer managerId, Integer id) {
        BmsManagerEntity entity = this.getById(managerId);

        //确定上下级关系
        if (!Objects.equals(id, entity.getHigherId())) {
            throw new BeanCreationException(CommonExceptionEnum.NOT_PERMISSION.getMsg());
        }
        return entity;
    }

    /**
     * @param managerId
     * @param managerEntity
     * @return void
     * @description 查询下级是否存在下级
     * @author zhangyiheng
     * @date 2024/9/12 13:52
     */
    private ResponseResult hasNext(Integer managerId, BmsManagerEntity managerEntity) {
        //查询下级是否存在下级
        if (!Objects.equals(managerEntity.getLevel(), DISTRICT)) {
            long count = this.count(Wrappers.<BmsManagerEntity>lambdaQuery()
                    .eq(BmsManagerEntity::getHigherId, managerId));
            if (count > 0) {
                return ResponseResult.errorResult(CommonExceptionEnum.SCSB_XX_CZQTXJCY.getCode(), StrUtil.format(CommonExceptionEnum.SCSB_XX_CZQTXJCY.getMsg(), managerEntity.getName()));
            }
        }
        return null;
    }


    /**
     * @param managerIds
     * @return void
     * @description 删除下级
     * @author zhangyiheng
     * @date 2024/9/12 12:41
     */
    @Override
    @Transactional
    public ResponseResult removeByIds(Integer[] managerIds, AccountInfo accountInfo) {
        Integer id = GlobalCheck.checkManagerAdmin(accountInfo.getManagerId());
        for (Integer managerId : managerIds) {
            //确定上下级关系
            BmsManagerEntity managerEntity = determineTheSubordinateRelationship(managerId, id);

            //判断状态
            if (Objects.equals(managerEntity.getStatus(), StatusEnum.ENABLED.getKey())) {
                return ResponseResult.errorResult(CommonExceptionEnum.SCSB_CZZZQYDXJ);
            }

            //查询下级是否存在下级
            ResponseResult responseResult = hasNext(managerId, managerEntity);
            if (!Objects.isNull(responseResult)) {
                return responseResult;
            }

        }
        //删除下级
        this.removeByIds(Arrays.asList(managerIds));

        //修改下级数量
        BmsManagerEntity manager = this.getById(id);
        this.update(Wrappers.<BmsManagerEntity>lambdaUpdate()
                .set(BmsManagerEntity::getTotalLower, Optional.ofNullable
                        (manager.getTotalLower()).orElse(0) - managerIds.length)
                .eq(BmsManagerEntity::getManagerId, manager.getManagerId()));

//        //TODO注销
//        for (Long managerId : managerIds) {
//            StpUtil.logout(managerId);
//        }
        return ResponseResult.ok();

    }


    @Override
    public Integer getIdByName(String managerName) {
        QueryWrapper<BmsManagerEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", managerName);
        BmsManagerEntity entity = baseMapper.selectOne(queryWrapper);
        if (entity != null) {
            return entity.getManagerId();
        }
        return -999;
    }

    @Override
    public ResponseResult getAllManagesInfo() {
        QueryWrapper<BmsManagerEntity> queryWrapper = new QueryWrapper<>();
        List<BmsManagerEntity> list = baseMapper.selectList(queryWrapper);
        if(list.size()>0){
            return ResponseResult.okResult(list);
        }
        return null;
    }

}